home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1997 May
/
EnigmA AMIGA RUN 18 (1997)(G.R. Edizioni)(IT)[!][issue 1997-05][EAR-CD II].iso
/
softwareupdate
/
system
/
amigados
/
files
/
files.doc
< prev
next >
Wrap
Text File
|
1996-10-10
|
41KB
|
1,096 lines
2 FILES
2.1 INTRODUCTION
In this chapter I will explain how to work with files. I will
describe how you open files, read as well as save data, and
finally close the file again. In this chapter I will also
explain how to work with files in a multitasking environment.
I will concentrate this chapter to only discuss the most
commonly used file functions. In the follwoing chapters you will
find more advanced routines like the "buffered IO" as well as
other types of useful function which you might need.
2.2 SOME GENERAL INFORMATION ABOUT FILES
If you have not worked with files before you might feel a bit
confused when you hear someone mention "file cursors" and
"exclusive locks" and so forth... However, do not dispair, I
will try to do my best to explain these things.
A "file" is simply a collection of data which have been stored,
and can later be retreived (read). Data can be stored on many
types of devices, but the most commonly used place to store
data is oundouptedly on a disk. Data can also be stored on
tapes, hard disks, laser disks, and so on...
A program can create a new file and store data in it, or it can
collect data from an already existing file. A program can also
append new data or alter data in an existing file.
When you want to use a file you first have to "open" it. When
you open a file AmigaDOS prepares the system and the file so
they can start to send and receive data.
AmigaDOS is using a "file cursor" which is like a pointer that
can be moved around inside the file like the pickup of a record
player. When you open a file the file cursor is always
positioned at the beginning of the file. Since all data in a
file are treated as bytes will the file cursor simply point to
the first byte in the file.
See picture "ReadWrite.pic". At the top of the picture you can
see a long rectangle filled with question marks. This is how
an empty disk may be illustrated. Since the disk is empty we
do not know what values are stored on it, if there are any,
therefore the question marks.
1. When we "open" the file (with help of the Open() function
which will be explained later on) the file cursor is
positioned at the beginning of the file, here illustrated
as a small arrow. You can see that the file cursor points
to the first byte in the file.
2. We then write some data to the file (with help of the
Write() function which will soon be explained). We send
the text "HELLO", and it will be stored in the file.
Remember that a file is like an array of bytes, and
consequently each letter is stored in a byte. A letter
(char) is treated as a byte by C, and you could
therefore equally well have sent the numbers 72, 69, 76,
76 and 79 which are the ASCII values of "HELLO".
When you send data to a file there is sometimes put a
a special "End Of File" sign at the end of the file. This
"EOF" sing (the constant "EOF" is defined as -1 in header
file "stdio.h") is used by some of the standard routines
in C, but actually NOT used by AmigaDOS. (AmigaDOS uses
instead some other routines to keep track of the file
length, but this will not be discussed here.)
However, although AmigaDOS does not use the EOF sign I
have included it in the picture since the file routines
acts like if there was a sign at the end of the file. The
EOF sign simply illustrates the end of the file although
it acutally is unknown byte as the following question
marks.
As you can see on the picture the text "HELLO" has been
stored in the file, one character (or byte if you so like)
in each box after each other. You can also see that the
file cursor now has moved and is pointing at the end of
the file, ready to add more data if necessary.
3. We now sends some data to the file again, and the text
" WORLD" is appended to the file. The file cursor is once
again moved to the end of the file ready to append even
more data.
4. If we now would like to read some of the data we have
stored we must first move the file cursor back to the
first character (byte) we want to read. (We move the file
cursor with help of the Seek() function which will as all
the other functions be explained in the following
sections. Here we tell AmigaDOS to move the file curser
three bytes foreward from the beginning of the file.)
5. We now read some data (with help of the Read() function)
which we have previously stored. In this example we read
seven characters (bytes) from the current position and
consequently we get the text "LO WORLD".
6. When you do not want to use the file any more you have to
"close" it so other programs can read and or modify it
later on. (To close a file you use the Close() function.)
The file cursor will then automatically be removed.
2.3 WORK WITH FILES
The procedure of working with files is relative simple. First
you have to declare a BCPL pointer (A BPTR) which you have to
use whenever you want to do something with the file.
/* A "BCPL" pointer to our file: */
BPTR my_file;
You should the "open" the file which will prepare the system so
later can use the file. To open files you use the "Open()"
function. Once you have opened the file you can start to read
data with help of the "Read()" function, write data with help
of the "Write()" function, as well as move the file cursor with
help of the "Seek()" function. When you do not want to use the
file any more you close it by calling the "Close()" function.
Sometimes when you have received an error you can call a
special function named "IoErr()" which will give you some more
information about the error. This function is, however, first
explained in chapter 8 "Miscellaneous" so you do not have to
bother about it yet.
2.3.1 OPEN THE FILE
Before you can do anything with a file you have to ask AmigaDOS
to "open" it. When you open a file you actualy tell the
computer what you would like to do with the file. You might
want to open a new file or an already existing one.
When you tell AmigaDOS that you want to open an old file the
file cursor will be positioned in the beginning of the old
file, pointing to the first byte. You can also open a file as
"new", and a new file will be created for you and the file
cursor is positioned in the beginning of the new file. If you
open an already existing file as a "new" file the existing file
will be deleted and a new one created for you.
To open files you should use the Open() function:
---------------------------------------------------------------
Open()
ROM library: "dos.library/Open", (All Versions)
#include <clib/dos_protos.h>
Opens a new or old file for input and/or output, and puts a
"read" or "write" lock on the file.
Synopsis: my_file = Open( file_name, mode );
my_file: (BPTR) If the file could be opened a BPTR (BPCL
pointer) is returned. If the file on the other
hand could not be opened NULL is returned.
file_name: (STRPTR) Pointer to a text string which contains
the name of the file you want to open. If the file
is not located in the current directory you have
to include any necessary device/directory names.
(The device/directory part is usually reffered as
the "path", and tells AmigaDOS where the file can
be found.)
mode: (LONG) When you want to open a file you must tell
AmigaDOS how you want to open the file. For the
mement there exist three modes: (The flags are
defined in header file "dos/dos.h")
MODE_OLDFILE: Opens an existing file for reading
and writing. The file will be
"locked" so other programs can read
it but not modify it before you
have "un-locked" the file. This is
usually called a "write lock"
("shared lock").
If the file does not exist or it
is used by some other program
("read or write locked") Open()
will fail and NULL is returned.
MODE_NEWFILE: Opens a new file for writing. If
the file already exist it will be
deleted so a new file with the
same name can be created.
Note that the data in an existing
file will be deleted if you use
this flag on an already existing
file! Be careful so you do not
destroy important data!
The file will be "locked" so no
other programs can read nor write
to it. This is usually called a
"read/write lock" ("exclusive
lock")
If the file already exist and is
used by some other program ("read
or write locked") Open() will fail
and NULL is returned.
MODE_READWRITE: Opens an old file as described
with the "MODE_OLDFILE" flag.
However, if the file does not
exist it will be created.
If the file is used by some other
program ("read or write locked")
Open() will fail and NULL is
returned.
Regardless of what mode you chose the file cursor
will always be positioned in the beginning of the
file if it could be opened. (The file cursor will
point to the first byte/character in the file).
You may of course have as many files open at the same time as
you want. Note that each file you have opened has its own file
cursor. When you work with one file you do not have to bother
about the other ones. If you move around inside one file the
others files' file cursors will remain unmodified. Of course
you need a BPTR for each file, and you have to open each file
separately.
Here is a simple example on how to use the Open() function:
/* A "BCPL" pointer to our file: */
BPTR my_file;
- - -
/* Try to open a file as "new": */
my_file = Open( "Highscore.dat", MODE_NEWFILE );
/* Check if we have successfully opened the file or not: */
if( my_file == NULL )
printf( "Could not open the file!\n" );
See also: Close(), IoErr(), Lock(), OpenFromLock(), Read(),
Seek(), UnLock(), Write()
---------------------------------------------------------------
2.3.2 READ DATA
Once you have successfully opened a file you can start to read
from it or write to it. AmigaDOS consider files to be a stream
of bytes, and every time you read a file you have to specify
how many bytes you want to read. To read a single character you
should read 1 byte since the size of a character is exactly one
byte. To read an integer you have to read 4 bytes, and so on...
Since you most of the time want to read complete structures or
arays of data it can be rather difficult to calculate the right
number of bytes if you have to do it yourself. Luckily there
exist a small function in C called "sizeof()" which simply
returns the size in bytes of a specified object:
Synopsis: size = sizeof( object );
size: The size of the specified object (in bytes).
object: The object you want to know the size of.
Example:
/* Get the size (in bytes) of an object: */
struct Screen my_screen;
size = sizeof( struct Screen );
If you want to get the size of a string you should use another
standard C function called "strlen()":
Synopsis: length = strlen( string );
length: The number of characters in the string. (Remember
that one character is equal to one byte.)
string: Pointer to a NULL terminated string you want to
examine.
Example:
/* Get the length (number of characters) in a string: */
UBYTE my_string = "The Amiga C Encyclopedia!";
length = strlen( my_string );
To read some bytes in a file you can use the Read() function.
It will collect a specified number of bytes starting from the
current position of the file cursor. The Read() function is
defined like this:
---------------------------------------------------------------
Read()
ROM library: "dos.library/Read", (All Versions)
#include <clib/dos_protos.h>
Reads a specified number of bytes in a file.
Synopsis: count = Read( file, buffer, size );
count: (LONG) The function returns the number of bytes
actually read. When you tell AmigaDOS that you want
to read X number of bytes it is not certain that you
actually can do it. The file might be shorter than
you expected or the file might be corrupted, etc...
The returned value can be:
1. equal to the number of bytes requested. In this
case everything went as expected. The requested
number of bytes were read, and there were no
errors.
2. equal to -1. In this case there was an error
while the function tried to read the data. How
much, if any, data were actually read before the
error occured is imposible to say, and you should
not use the values in the buffer. If you receive
this value you may call IoErr() to get more
information about the error.
3. less than the number of bytes requested, but
not equal to -1. In this case we have simply
reached the end of the file, and there was no
error.
Please note that reaching the end of the file
before expected can sometimes indicate that there
was some sort of error. If you have saved for
example 10 structures of a certain size, and when
you later tries to read the file and only get four
structures there is obviously something wrong. It
is, however, not a dos error and the file itself
is ok. It is the data in the file which is
incorrect, but that is not AmigaDOS's fault.
file: (BPTR) A BCPL pointer to an already open file.
buffer: (APTR) Pointer to some memory where the collected
data can be stored.
size: (LONG) Number of bytes you want to read.
Note! The function does not check that the buffer you give it
is big enough to store all values you requested! You may never
try to read more bytes than can fit in your buffer!
Here is a simple example on how to use the Read() function:
/* Some memory where we will store the collected data: */
int my_highscore[ 10 ];
/* The number of bytes actually collected: */
long bytes_read;
- - -
/* Read some data from an already open file: */
bytes_read = Read( my_file, my_highscore, sizeof( my_highscore ) );
/* Did we get all data? */
if( bytes_read != sizeof( my_highscore ) )
{
/* No! We could not read all values! */
printf( "Error! Could read all values!\n" );
}
else
{
/* Yes! All recuested data were successfully collected! */
printf( "Data collected!\n" );
}
See also: Close(), IoErr(), Lock(), Open(), OpenFromLock(),
Seek(), UnLock(), Write()
---------------------------------------------------------------
2.3.3 WRITE DATA
To write some data (bytes) to a file you can use the Write()
function. It will write a specified number of bytes starting
from the current position of the file cursor. The Write()
function is defined like this:
---------------------------------------------------------------
Write()
ROM library: "dos.library/Write", (All Versions)
#include <clib/dos_protos.h>
Writes a specified number of bytes to a file.
Synopsis: count = Write( file, buffer, size );
count: (LONG) The function returns the number of bytes
actually written. When you tell AmigaDOS that you want
to write X number of bytes it is not certain that you
actually can do it. The file is maybe write protected,
or the disk is full etc...
The returned value can be:
1. equal to the number of bytes requested. In this
case everything went as expected. The requested
number of bytes were written, and there were no
errors.
2. equal to -1. In this case there was an error
while the function tried to write the data. No
data will have been saved. If you receive this
value you may call IoErr() to get more information
about the error.
3. less than the number of bytes requested, but
not equal to -1. In this case the operation was
aborted because of some external event (disk full
etc...), and the value returned tells us how many
bytes that have been saved.
If you could not save all the data you should
in most situations remove the half filled file
(it is probably useless if not all data could
be saved) and ask the user to for example insert
a new disk etc... depending on what have happened.
Do NOT just tell the user that there was a problem
and then quit! (In small examples and if the data
is unimportant this is of course OK, but bigger
applications should try to solve the problem.)
file: (BPTR) A BCPL pointer to an already open file.
buffer: (APTR) Pointer to some memory where the data that
should be written (saved) are stored.
size: (LONG) Number of bytes you want to write.
Here is a simple example on how to use the Write() function:
/* Some data we want to save: */
int my_highscore[ 10 ] =
{ 34, 76, 328, 723, 1027, 1201, 1416, 2645, 3050, 3876 };
/* The number of bytes actually written: */
long bytes_written;
- - -
/* Write some data to a file: */
bytes_written = Write( my_file, my_highscore, sizeof( my_highscore ) );
/* Did we write all data? */
if( bytes_written != sizeof( my_highscore ) )
{
/* No! We could not write (save) all data! */
printf( "Error! Could not save all values!\n" );
}
else
{
/* Yes, all numbers have been written to the file! */
printf( "All values were saved successfully!\n" );
}
See also: Close(), IoErr(), Lock(), Open(), OpenFromLock(),
Read(), Seek(), UnLock()
---------------------------------------------------------------
2.3.4 MOVE INSIDE A FILE
The Read() and Write() functions will start their operations at
the byte which the file cursor is currently pointing to. When
you open a file the file curser is positioned at the beginning
of the file. This may of course not be the position you desire.
If you, for example, want add data to the file you need to move
the file cursor to the end of the file. If you on the other
hand have just written some data to a file and would like to
read it again you have to move the file cursor back to the
positon you want to start to read at.
To move the file cursor you should use the "Seek()" function.
You tell it which position you want to move to. The position is
relative to a specified "offest position" which can either be
the beginning of the file, the current position, or the end of
the file. (See picture "OffsetPosition.pic")
The Seek() function is defined like this:
---------------------------------------------------------------
Seek()
ROM library: "dos.library/Seek", (All Versions)
#include <clib/dos_protos.h>
Moves the file cursor to a specified position in a file.
Synopsis: old_pos = Seek( file, position, offset );
old_pos: (LONG) The function returns the previous position
in the file, or -1 if there was an error and the
file cursor could not be moved. If there was an
error you should of course not try to read or
write any data until the problem has been solved
and you have successfully positioned the file
cursor.
If there is an error you should call IoErr() to
get more information about the error.
file: (BPTR) A BCPL pointer to an already open file.
position: (LONG) The position you want to move the file
cursor to. Note that this value is an relative
to the specified "offset position".
offest: (LONG) The specified position is relative to one
one of these "offset positions": (The flags are
defined in header file "dos/dos.h")
OFFSET_BEGINNING: Beginning of the file.
OFFSET_CURRENT: Current position.
OFFSET_END: The end of the file.
If you want to move the file cursor to the beginning of the
file (pointing to the first byte) you set the offset position
to "OFFSET_BEGINNING" and the position value to 0.
If you on the other hand want to move the file cursor to the
end of the file you set the offset position to "OFFSET_END" and
the position value to 0.
To move 10 bytes forward from the current position you set the
offset position to "OFFSET_CURRENT" and the position value to
10. To move 10 bytes backwards you set the position value to
-10.
Here are some simple examples on how to use the Seek() function:
/* Move the file cursor to the end of the file: */
Seek( my_file, 0, OFFSET_END );
/* Move the file cursor to the beginning of the file: */
Seek( my_file, 0, OFFSET_BEGINNING );
/* Move the file cursor 10 bytes forward */
/* from the current position: */
Seek( my_file, 10, OFFSET_CURRENT );
/* Move the file cursor 10 bytes backwards */
/* from the current position: */
Seek( my_file, -10, OFFSET_CURRENT );
See also: Close(), IoErr(), Lock(), Open(), OpenFromLock(),
Read(), UnLock(), Write()
---------------------------------------------------------------
2.3.5 CLOSE THE FILE
Once you have finished working with the file and do not want to
use it any more you must "close" it. When you close a file will
the file cursor be removed, and other programs can now start to
use the file.
Note that if you opened the file with a "shared lock" (only
"write lock") other programs have been able to read the file
but have not been able to modify it. If you opened the file
with an "exclusive lock" ("read and write lock") no other
programs have been able to read it nor to modify it.
Since other programs are "locked out" when you open a file it
is very important that you close the file later on when you do
not need it so other programs can use the file. Note that every
file you have opened must be closed!
*********************************************************
* *
* REMEMBER! Every file you have opened MUST be closed *
* when you do not need it any more! *
* *
*********************************************************
It is very important that you close all files you have opened,
and this must of course also be done if your program discovers
an error and terminates. Sadly many programmers forget to
clean up after themself if their program has to terminate
because of an error. Please be careful with this!
To close a file you should use the "Close()" function which is
defined like this:
---------------------------------------------------------------
Close()
ROM library: "dos.library/Close", (All Versions)
#include <clib/dos_protos.h>
Closes a previously opened file.
Synopsis: ok = Close( file );
ok: (LONG) If the file could successfully be saved TRUE
is returned. On the other hand, if there was some
sort of problem FALSE is returned.
Even if the file could not be closed successfully
will the file cursor and all memory which have
previously been allocated internally now been
removed and deallocated. So even if you could not
close the file successfully you should NOT try to
close it again (that would crash the system)!
If the file could not be closed there is actually
very little we can do about it. We might want to
resave some data (in another file) if we are afraid
the data otherwise might be lost, but we can not
do anything about the actual error. Just remember
that you must not try to close the file again, nor
to use it any more!
On the old systems prior to Release 2 (older than
V36) the Close() do not return anything.
file: (BPTR) A BCPL pointer to an already open file which
should now be cosed.
Remember to close ALL files you have opened!
Here is a simple example on how to use the Close() function:
- - -
/* Close the file: */
if( Close( my_file ) )
printf( "File closed!\n" );
else
printf( "Error! File could not be closed!\n" );
/* Remember that even if the file could not be */
/* closed we must NOT try to close it again! */
See also: IoErr(), Lock(), Open(), OpenFromLock(), Read(),
Seek(), UnLock(), Write()
---------------------------------------------------------------
2.4 FILES AND MULTITASKING
Since the Amiga can have several programs running at the same
time it can happen that several programs work with the same
file. This can be very dangerous since two programs may work
simultaneously with one file. What one program creats may be
destroyed by the other program, and this type of problem is
ften called "the lost update problem".
2.4.1 THE LOST UPDATE PROBLEM
Imagine that you have two programs which are used alter some
values in a file. Program "A" should multiply the values by 2.
When "A" has updated the values program "B" should add 3.
If you look at the picture "LostUpdate.pic" you will see what
can happen if you are very unlucky. Program "A" reads the value
10 and starts to calculate the answer. While "A" is busy
working with the number program "B" starts and also reads the
value before "A" has updated it! Program "B" will therefore
also get the value 10.
Program "A" has now finished its calculations and writes the
updated value 20 to the file. The program "B" finish its
calculation and stores the value 13. As you can see has the
update program "A" made been lost! This is why this type of
error is called "the lost update problem".
2.4.2 SOLVE THE LOST UPDATE PROBLEM
This type of problems with lost updates can luckily be avoided
if the programs are "locking" the files. When a program "locks"
a file no other program can use the file until the file has
been unlocked. Whenever you are writing programs that may
alter data in files other programs also work with you should be
very careful to lock the files when necessary.
If the programs as described had locked the file while they
were using it there would never have been any problems. See
pricture "UpdateOK.pic". The first thing program "A" does is
this time to lock the file. Program "A" can then read any
values and do its calculation with them, and can be absolute
sure that no other program can use the file.
Program "B" is maybe trying to read the file, but will not be
able to open it, so it has to wait. Once "A" has finished the
calculations it writes the new value to the file and then
unlocks the file. Prgram "B" can now open the file a and locks
it to prevent other programs to use the file. Program "B" does
its calculations and then stores the new value in the file, and
the file is unlocked.
Since the programs were locking the file while they were using
it there were no values lost. The problem with the lost update
has been solved.
2.4.3 WHEN FILES SHOULD BE LOCKED
On large mainframe computers there exist many different types
of locks with different priorities, but on the Amiga there
exist only two different types of locks. You can lock a file
so other programs may read it but not change it ("shared
lock"), or if you do not want any other tasks to even read the
file you set an "excluseive lock".
When you open a file with help of the Open() function you will
automatically get a lock on the file. If you opened the file
as a "new file" (MODE_NEWFILE) you will get an exclusive lock,
and no other programs will be able to use the file until you
close it.
However, if you have opened an "old" file (MODE_OLDFILE) or
used the secial "read/write" option (MODE_READWRITE) the file
will get a "shared lock". Other programs may therefore also
read the file while you are working with it. (Whenever you
save some data in the file it will temporarily be exclusive
locked, but that will be converted into a normal shared lock
as soon as all data has been witten.)
When you have opened a new file you will not need to lock the
file yourself since it is already exclusive locked. If you
have, on the other hand, opened an old file or used the read/
write mode you might need to lock the file to prevent other
programs to read it while you are working with it.
The only problem is actually when you should lock a file and
when not. A wordprocessors that works with a document usually
never locks the actual dockument. Normally the wordprocessor
even closes the file after it has read it, and opens it only
temporarily while it saves the document. The file will
therefore be completely "unlocked" while the wordprocessors
is running!
If this is good or not can be discussed:
(+) The advantage is that the file can be deleted or altered
by other programs while the wordprocessors is still
running. The user is free to do what he or she wants with
the file while the wordprocessors is running.
(-) The disadvantage is that the user can do whatever he/she
likes with the file (some thinks this is an advantage as
described above).
For example: A user is editing a document and while the
wordprocessor is running he/she tries to start a program
that alters the file (the user is maybe using an extrnal
spell checker, or some type of "reformatting" program)
he/she will be allowed to do that. The problem comes if
the user then (after he/she has spellchecked and
reformatted the file) saves the document in the
wordprocessors. All alterations which were done to the
file will then be lost as described before!
Personally I believe that most programs should keep at least a
shared lock on the file while the program is using it. The
external spell checker as described would in this case still be
able to read the file (some freedom for the user), but when the
spelchecker tries to save the data it will fail and the user is
alerted and forced to create a new file for the spell checked
data.
One possible solution would be that the wordprocessors alerts
the user whenever a file is going to be over written. In this
case the user would also be warned that data might be lost.
However, one problem remains. What would happen if the user
deletes the file (a copy of it is in the wordprocessor the user
thinks so it does not matter...) and then suddenly there is
power cut?
There exist a simple "rule" of when you should use an exclusive
lock on a file and when you can use a shared lock:
When files are altered automatically (without any action from
the user) you should keep an exclusive lock on the file if
possible. Automatic functions can very easily create
unexpected situations and updated data might be lost (as
described in our examle with the two programs "A" and "B").
When files are altered because of some action from the user
it might be enough with a shared lock (if necesary). This
depends of course on how much you trust the user (another
"programming rule" is that you should never trust the user,
and in such case you should actually use an exclusive lock).
2.4.4 LOCK FILES
When you want to put a lock on a file you should use the
"Lock()" function. When you are working with files you actually
only need to use this function when you want to add an
exclusive lock to a file. At least a shared lock will have
automatically been added for you when you opened the file (if
you open a new file you will even get an exclusive lock).
This Lock() function is, however, also needed when you are
working with some special file functions which will be
descrbed in the following chapters.
The Lock() function is defined like this:
---------------------------------------------------------------
Lock()
ROM library: "dos.library/Lock", (All Versions)
#include <clib/dos_protos.h>
Puts a shared or excusive lock on an object (e.g. file).
Synopsis: lock = Lock( file_name, mode );
lock: (BPTR) If the file could be locked a BPTR (BPCL
pointer) is returned. If the file on the other
hand could not be locked NULL is returned.
Possible reasons why the lock failed:
1. The file simply does not exist.
2. Some other program has an exclusive lock on
the file, and consequntly no others may lock
it (both shared and exclusive lock requests
will fail).
3. Som other program has a shared lock on the
file but you wanted an exclusive lock. (If
the file has a shared lock on it, and you
tries to add another shared lock on it there
will not be any problems.)
file_name: (STRPTR) Pointer to a text string which contains
the name of the file you want to lock. If the file
is not located in the current directory you have
to include the necessary path.
mode: (LONG) On the Amiga there exist two types of
locks: (The flags are defined in header file
"dos/dos.h")
SHARED_LOCK: Other programs may read data in
the file, but no one else may
alter the file. (You can also
use the flag "ACCESS_READ"
which does the same thing.)
EXCLUSIVE_LOCK: No other programs may use this
file. (You can also use the
flag "ACCESS_WRITE" which does
the same thing.)
Here is a simple example on how to use the Lock() function:
/* A "BCPL" pointer to our lock: */
BPTR my_lock;
- - -
/* Try to lock the file with an exclusive lock: */
my_lock = Lock( "Highscore.dat", EXCLUSIVE_LOCK );
/* Check if we have successfully locked the file or not: */
if( my_lock == NULL )
printf( "Could not lock the file!\n" );
See also: Close(), IoErr(), Open(), OpenFromLock(), Read(),
Seek(), UnLock(), Write()
---------------------------------------------------------------
2.4.5 UNLOCK FILES
Whenever you do not need a lock on a file you must unlock it.
***********************************************************
* *
* REMEMBER! Every file you have locked MUST be unlocked *
* when you do not need the lock any more! *
* *
***********************************************************
To unlock a file simply call the "UnLock()" function and give
it the lock that should be unlocked. The UnLock() function is
defined like this:
---------------------------------------------------------------
UnLock()
ROM library: "dos.library/UnLock", (All Versions)
#include <clib/dos_protos.h>
Unlocks a previously locked object (e.g. file).
Synopsis: UnLock( lock );
lock: (BPTR) A BPCL pointer to a lock that should be
unlocked. Remember that every file that you have
locked must be unlocked when you do not need the
look any more!
Here is a simple example on how to use the UnLock() function:
- - -
/* Unlock the file: */
UnLock( my_lock );
See also: Close(), IoErr(), Lock(), Open(), OpenFromLock(),
Read(), Seek(), Write()
---------------------------------------------------------------
2.4.6 OPEN A LOCKED FILE
If you have open a file and want to put an exclusive lock on it
the Lock() function will fail. The reason why it will fail is
because the file is currently used by someone (in this case
yourself since you have opened the file), and you can therefore
not put an exclusive lock on the file. The problem is that you
can not do the opposit eiter, you can not lock a file
exclusively and then try open it since the Open() function will
then fail.
Now it seems like it would be impossible to use an old file and
still be able to put an exclusive lock on it. (New files will
automaticaly get an exclusive lock.) The fact is that prior to
Release 2 it was impossible (unless you did some low level
work). However, with Release 2 a new open function,
"OpenFromLock()", was introduced. If the user has dos version
36 or higher you can lock the file (exclusive or shared,
although shared is unnecessary since that is done automatically
when you open the file) and then use this new function to open
the file with help of the lock.
Please remember to check that the user really have dos library
V36 or higher before you try to call the OpenFromLock()
function!
The OpenFromLock() function is defined like this:
---------------------------------------------------------------
OpenFromLock()
ROM library: "dos.library/OpenFromLock", (V36+)
#include <clib/dos_protos.h>
Opens an already locked file.
Synopsis: my_file = OpenFromLock( lock );
my_file: (BPTR) If the file could be opened a BPTR (BPCL
pointer) is returned. If the file on the other hand
could not be opened NULL is returned.
lock: (BPTR) A BPCL pointer to a lock which file should be
opened. You must of course have locked the file
successfully before you may open the file with it!
Here is a simple example on how to use the OpenFromLock()
function:
/* A "BCPL" pointer to our lock: */
BPTR my_lock;
/* A "BCPL" pointer to our file: */
BPTR my_file;
- - -
/* Put an exclusive lock on an existing file: */
my_lock = Lock( "RAM:HighScore.dat", EXCLUSIVE_LOCK );
/* Could we lock the file successfully? */
if( !my_lock )
{
/* Problems! Inform the user: */
printf( "Could not put an exclusive lock on the file!\n" );
/* Exit with an error code: */
exit( 20 );
}
/* We will now try to open the file with help */
/* of the lock we already have: */
my_file = OpenFromLock( my_lock );
/* Have we opened the file successfully? */
if( !my_file )
{
/* Problems! Inform the user: */
printf( "Error! Could not open the file!\n" );
/* Unlock the file: */
UnLock( my_lock );
/* Exit with an error code: */
exit( 21 );
}
- - -
/* Close the file: */
Close( my_file );
/* Unlock the file: */
UnLock( my_lock );
See also: Close(), IoErr(), Lock(), Open(), Read(), Seek(),
UnLock(), Write()
---------------------------------------------------------------
2.5 OTHER FILE FUNCTIONS
Up to now we have discussed the elementary parts on how to work
with files. We have looked at how to open, work with and close
files, as well as how to use any necessary locks. This is
enough for small applications, but you might need to do more
things with the files. There exist a lot of useful support
functions which will be described in the next chapter "File
Functions".